#ifndef __MVT_ENCRYPTION_H__
#define __MVT_ENCRYPTION_H__

#include "mvdef.h"

MVCXX_EXTERN_BEGIN

/**
 * @brief 智能内存申请 机制
 * @note ppv8_output 入参实体指向可以为NULL,且s32_out_max为0时，代表启用【智能内存申请】机制
 *       自动申请满足的缓存长度内容，并赋值 ppv8_output 出参；
 *         e.g. mv_vptr_t p = NULL; mvt_base32_encode_r(&p, 0, ...);
 *       s32_out_max 为非0时，代表普通模式， ppv8_output 应为实体地址，使用(mv_v8ptr_t*)方式进行异变传参，以符合调用方法；
 *         e.g. mv_v8_t av8_buf[16] = {0}; mvt_base32_encode_r((mv_u8ptr_t*)av8_buf, 16, ...);
 * @note 使用【智能内存申请】机制后，调用者须在不再需要使用的时候，自行调用mvos_free释放该内存块，避免内存泄露！
 * @note 该机制仅适用于【智能内存申请】的接口，普通接口不受影响
 */

/**
 * @brief base32编码（智能内存申请）
 * 
 * @param ppv8_output [out] 输出结果
 * @param s32_out_max [in]  输出结果最大长度
 * @param pu8_input   [in]  输入数据
 * @param s32_in_len  [in]  输入数据长度(0:自动计算；注意数据包含'\0'时，需传入实际长度)
 * @return 编码结果
 * - success : >=0编码后实际长度
 * -  failed : MV_EC_INVALID_ARGS  (非法入参，入参NULL或输入数据包含非base32字符）
 *             MV_EC_OUT_OF_RANGE  (解码后输出长度超出outmax限制)
 *             MV_EC_MALLOC_FAILED (内存不足，【智能内存申请】时)
 *             else异常结果 
 * @note 详细机制参照【智能内存申请】机制描述
 */
mv_s32_t mvt_base32_encode_s(mv_v8ptr_t *ppv8_output, mv_s32_t s32_out_max, mv_u8ptr_t pu8_input, mv_s32_t s32_in_len);
/**
 * @brief base32解码（智能内存申请）
 * 
 * @param pu8_output  [out] 输出结果
 * @param s32_out_max [in]  输出结果最大长度
 * @param pv8_input   [in]  输入数据
 * @param s32_in_len  [in]  输入数据长度(0:自动计算)
 * @return 解码结果
 * - success : >=0解码后实际长度
 * -  failed : MV_EC_INVALID_ARGS  (非法入参，入参NULL或输入数据包含非base32字符）
 *             MV_EC_OUT_OF_RANGE  (解码后输出长度超出outmax限制)
 *             else异常结果 
 * @note 详细机制参照【智能内存申请】机制描述
 */
mv_s32_t mvt_base32_decode_s(mv_u8ptr_t *ppu8_output, mv_s32_t s32_out_max, mv_v8ptr_t pv8_input, mv_s32_t s32_in_len);

mv_s32_t mvt_base64_encode(mv_v8ptr_t pv8_dst, mv_s32_t s32_dst_size, mv_cu8ptr_t cpu8_src, mv_s32_t s32_src_size);
mv_s32_t mvt_base64_decode(mv_u8ptr_t pu8_dst, mv_s32_t s32_dst_size, mv_cv8ptr_t cpv8_src, mv_s32_t s32_src_size);
/**
 * @brief base64编码2
 * 
 * @param cpu8_src      [in] 原始数据
 * @param s32_src_size  [in] 原始数据长度
 * @param ps32_result  [out] 输出结果：>=0编码后实际长度；else异常结果
 * @return 编码输出结果
 * - success : 编码后数据缓存起始地址（堆,需要自行mvos_free释放）
 * -  failed : NULL
 */
mv_v8ptr_t mvt_base64_encode_r(mv_cu8ptr_t cpu8_src, mv_s32_t s32_src_size, mv_s32ptr_t ps32_result);

typedef enum __mvt_hash_type {
    MVT_HASH_MD5,
    MVT_HASH_SHA1,
    MVT_HASH_SHA256,
    MVT_HASH_SHA512,
    MVT_HASH_NUM,
} mvt_hash_type_e;

mv_s32_t mvt_hash_start (mv_v8_t pv8_handle[256], mvt_hash_type_e e_type, mv_cu8ptr_t cpu8_hmac_secret, mv_s32_t s32_secret_len);
mv_s32_t mvt_hash_update(mv_v8_t pv8_handle[256], mv_cu8ptr_t cpu8_msg, mv_s32_t s32_len);
mv_s32_t mvt_hash_finish(mv_v8_t pv8_handle[256], mv_u8ptr_t pu8_digest);

typedef enum _mvt_cipher_type {
    MVT_CIPHER_NONE         = 0,
    MVT_CIPHER_AES128_ECB,
    MVT_CIPHER_AES128_CBC,

    MVT_CIPHER_SUPPORT_MAX,
#define MVT_CIPHER_SUPPORT_NUM (MVT_CIPHER_SUPPORT_MAX-1)
}mvt_cipher_type_e;

typedef enum _mvt_cipher_operation {
    MVT_CIPHER_DECRYPT      = 0,
    MVT_CIPHER_ENCRYPT      = 1,
}mvt_cipher_operation_e;

typedef enum _mvt_cipher_padding {
    MVT_CIPHER_PADDING_PKCS7 = 0, ///< PKCS7 padding (default).
    MVT_CIPHER_PADDING_ZEROS,     ///< Zero padding (not reversible).
    MVT_CIPHER_PADDING_NONE,      ///< Never pad (full blocks only).
}mvt_cipher_padding_t;

/**
 * @brief 初始化cipher句柄
 * 
 * @param av8_handle  [in] cipher处理用句柄，提供一个可读写的256字节大小的内存块即可
 * @param e_operation [in] 操作类型：加密 / 解密
 * @param e_type      [in] 加解密方法
 * @param e_pad_type  [in] 自动填充对齐方式
 * @param pu8_key     [in] 加解密使用密钥（根据加密方法自行判断传入密钥真实长度）
 * @param pu8_iv      [in] 个别加解密方法使用的初始化向量（根据加密方法使用要求自行判断是否传入，及传入的真实长度）
 * @return 初始化结果 \n
 * - success : MV_EC_SUCCESS \n
 * -  failed : else
 * @note 当选择MVT_CIPHER_PADDING_NONE不自动对齐时，要自行处理输入数据的对齐性，否则process操作会失败
 */
mv_s32_t mvt_cipher_start(mv_v8_t av8_handle[256], mvt_cipher_operation_e e_operation, mvt_cipher_type_e e_type, mvt_cipher_padding_t e_pad_type, mv_u8ptr_t pu8_key, mv_u8ptr_t pu8_iv);
/**
 * @brief 进行cipher处理
 * 
 * @param av8_handle [in] cipher处理用句柄（由"mvt_cipher_start"初始化）
 * @param pu8_input  [in] 需要处理的输入数据地址
 * @param s32_ilen   [in] 需要处理的输入数据长度
 * @param pu8_output [in] 处理后数据缓存地址
 * @param ps32_olen  [in] 当次已处理的数据长度(异常时<0，表示mbedtls的错误码)
 * @return 处理结果
 * - success : MV_EC_SUCCESS
 * -  failed : else
 * @note 当选择任一自动对齐方式时，输入数据在process时会进行自动对齐 \n
 *       pu8_output输出缓存内存长度必须确保预留足够空间（对齐长度 + 一个对齐块长度），否则会导致不可预期问题
 */
mv_s32_t mvt_cipher_process(mv_v8_t av8_handle[256], mv_u8ptr_t pu8_input, mv_s32_t s32_ilen, mv_u8ptr_t pu8_output, mv_s32ptr_t ps32_olen);
/**
 * @brief 剩余未处理数据的对齐处理，以及释放cipher句柄
 * 
 * @param av8_handle [in] cipher处理用句柄（由"mvt_cipher_start"初始化）
 * @param pu8_output [in] 处理后数据缓存地址
 * @param ps32_olen  [in] 当次已处理的数据长度(异常时<0，表示mbedtls的错误码)
 * @return 释放结果
 * - success : MV_EC_SUCCESS
 * -  failed : else
 */
mv_s32_t mvt_cipher_finish(mv_v8_t av8_handle[256], mv_u8ptr_t pu8_output, mv_s32ptr_t ps32_olen);

MVCXX_EXTERN_END

#endif